package zgrjb.snbq.teach_platform.component;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.*;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 消息WebSocket处理器
 * 处理实时私聊消息
 * 
 * @author system
 * @since 2024-12-28
 */
@Component
@Slf4j
public class MessageWebSocketHandler implements WebSocketHandler {

    // 存储用户会话，key为用户ID，value为WebSocket会话
    private static final Map<Long, WebSocketSession> userSessions = new ConcurrentHashMap<>();
    private final ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        log.info("消息WebSocket连接建立: {}", session.getId());
        
        // 从session中获取用户ID（这里需要根据实际的认证方式获取）
        Long userId = getUserIdFromSession(session);
        if (userId != null) {
            userSessions.put(userId, session);
            log.info("用户 {} 的消息WebSocket连接已建立", userId);
        }
    }

    @Override
    public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
        if (message instanceof TextMessage) {
            handleTextMessage(session, (TextMessage) message);
        }
    }

    private void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        log.info("收到消息WebSocket消息: {}", message.getPayload());
        
        try {
            Map<String, Object> msgData = objectMapper.readValue(message.getPayload(), Map.class);
            String type = (String) msgData.get("type");
            
            switch (type) {
                case "ping":
                    handlePing(session);
                    break;
                case "message":
                    handlePrivateMessage(session, msgData);
                    break;
                case "typing":
                    handleTypingStatus(session, msgData);
                    break;
                default:
                    log.warn("未知消息类型: {}", type);
            }
        } catch (Exception e) {
            log.error("处理消息WebSocket消息失败", e);
        }
    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        log.error("消息WebSocket传输错误: {}", session.getId(), exception);
        removeSession(session);
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
        log.info("消息WebSocket连接关闭: {}, 状态: {}", session.getId(), closeStatus);
        removeSession(session);
    }

    @Override
    public boolean supportsPartialMessages() {
        return false;
    }

    /**
     * 处理ping消息
     */
    private void handlePing(WebSocketSession session) throws IOException {
        String pongMessage = objectMapper.writeValueAsString(Map.of(
            "type", "pong",
            "timestamp", System.currentTimeMillis()
        ));
        session.sendMessage(new TextMessage(pongMessage));
    }

    /**
     * 处理私聊消息
     */
    private void handlePrivateMessage(WebSocketSession session, Map<String, Object> msgData) throws IOException {
        Map<String, Object> data = (Map<String, Object>) msgData.get("data");
        Long toUserId = Long.valueOf(data.get("toUserId").toString());
        String content = (String) data.get("content");
        
        // 获取发送者用户ID
        Long fromUserId = getUserIdFromSession(session);
        
        // 构建消息响应
        String messageResponse = objectMapper.writeValueAsString(Map.of(
            "type", "message",
            "data", Map.of(
                "fromUserId", fromUserId,
                "toUserId", toUserId,
                "content", content,
                "timestamp", System.currentTimeMillis()
            )
        ));
        
        // 发送给接收者
        WebSocketSession receiverSession = userSessions.get(toUserId);
        if (receiverSession != null && receiverSession.isOpen()) {
            receiverSession.sendMessage(new TextMessage(messageResponse));
        }
        
        // 发送确认给发送者
        String confirmResponse = objectMapper.writeValueAsString(Map.of(
            "type", "message_sent",
            "data", Map.of(
                "toUserId", toUserId,
                "status", "delivered",
                "timestamp", System.currentTimeMillis()
            )
        ));
        session.sendMessage(new TextMessage(confirmResponse));
    }

    /**
     * 处理正在输入状态
     */
    private void handleTypingStatus(WebSocketSession session, Map<String, Object> msgData) throws IOException {
        Map<String, Object> data = (Map<String, Object>) msgData.get("data");
        Long toUserId = Long.valueOf(data.get("toUserId").toString());
        Boolean isTyping = (Boolean) data.get("isTyping");
        
        Long fromUserId = getUserIdFromSession(session);
        
        String typingResponse = objectMapper.writeValueAsString(Map.of(
            "type", "typing",
            "data", Map.of(
                "fromUserId", fromUserId,
                "isTyping", isTyping,
                "timestamp", System.currentTimeMillis()
            )
        ));
        
        WebSocketSession receiverSession = userSessions.get(toUserId);
        if (receiverSession != null && receiverSession.isOpen()) {
            receiverSession.sendMessage(new TextMessage(typingResponse));
        }
    }

    /**
     * 发送消息给指定用户
     */
    public static void sendToUser(Long userId, Object message) {
        WebSocketSession session = userSessions.get(userId);
        if (session != null && session.isOpen()) {
            try {
                ObjectMapper mapper = new ObjectMapper();
                String jsonMessage = mapper.writeValueAsString(message);
                session.sendMessage(new TextMessage(jsonMessage));
            } catch (Exception e) {
                log.error("发送WebSocket消息给用户 {} 失败", userId, e);
            }
        }
    }

    /**
     * 广播消息给所有在线用户
     */
    public static void broadcast(Object message) {
        ObjectMapper mapper = new ObjectMapper();
        userSessions.values().forEach(session -> {
            if (session.isOpen()) {
                try {
                    String jsonMessage = mapper.writeValueAsString(message);
                    session.sendMessage(new TextMessage(jsonMessage));
                } catch (Exception e) {
                    log.error("广播WebSocket消息失败", e);
                }
            }
        });
    }

    /**
     * 从session中获取用户ID
     * 这里需要根据实际的认证方式来实现
     */
    private Long getUserIdFromSession(WebSocketSession session) {
        // 这里可以从session的attributes中获取用户信息
        // 或者从query参数中获取token然后解析
        // 暂时返回一个示例用户ID
        String query = session.getUri().getQuery();
        if (query != null && query.contains("userId=")) {
            String userIdStr = query.substring(query.indexOf("userId=") + 7);
            if (userIdStr.contains("&")) {
                userIdStr = userIdStr.substring(0, userIdStr.indexOf("&"));
            }
            try {
                return Long.valueOf(userIdStr);
            } catch (NumberFormatException e) {
                log.warn("无法解析用户ID: {}", userIdStr);
            }
        }
        return 1L; // 默认用户ID，实际应该从token中解析
    }

    /**
     * 移除会话
     */
    private void removeSession(WebSocketSession session) {
        Long userId = getUserIdFromSession(session);
        if (userId != null) {
            userSessions.remove(userId);
            log.info("移除用户 {} 的消息WebSocket连接", userId);
        }
    }

    /**
     * 获取在线用户数量
     */
    public static int getOnlineUserCount() {
        return userSessions.size();
    }
} 